// 请求拦截器
import Request from "./request";
import type { InternalRequestConfig, ResponseData } from "./types";
import type { AxiosResponse } from "axios";
import { toast } from "@/utils/toast";

const Api = new Request();

/**
 * 清理对象中的空值（null、undefined、空字符串）
 * @param obj 要清理的对象
 * @returns 清理后的对象
 */
function cleanEmptyValues<T extends Record<string, any>>(obj: T | null | undefined): T {
    if (!obj || typeof obj !== "object") {
        return {} as T;
    }

    const cleaned = { ...obj };
    for (const key in cleaned) {
        if (Object.prototype.hasOwnProperty.call(cleaned, key)) {
            const value = cleaned[key];
            // 删除 null、undefined 和空字符串
            if (value === null || value === undefined || value === "") {
                delete cleaned[key];
            }
        }
    }
    return cleaned;
}

/**
 * 获取错误消息
 * @param data 响应数据
 * @param defaultMsg 默认消息
 * @returns 错误消息
 */
function getErrorMessage(data: ResponseData | undefined, defaultMsg: string): string {
    return data?.msg || data?.message || defaultMsg;
}

// ==================== 请求拦截器 ====================
Api.interceptors.request((config: InternalRequestConfig) => {
    const token = localStorage.getItem("token") || "";

    // 初始化 headers（确保不为 undefined）
    config.headers = config.headers || ({} as any);

    // 显示加载提示
    if (config.loading) {
        toast.loading("请稍等...");
    }

    // 设置认证 token
    if (token) {
        config.headers["Authorization"] = `Bearer ${token}`;
    }

    // 设置租户 ID
    config.headers["tenant-id"] = "1";

    // 设置 Content-Type
    const method = config.method?.toLowerCase();
    if (method === "get") {
        config.headers["Content-Type"] = "application/x-www-form-urlencoded";
    } else if (!config.headers["Content-Type"]) {
        config.headers["Content-Type"] = "application/json";
    }

    // 清理请求体中的空值
    config.data = cleanEmptyValues(config.data);

    // 清理查询参数中的空值
    config.params = cleanEmptyValues(config.params);

    // 调试日志
    console.log(`[请求] ${config.apiName || config.url}`, {
        method: config.method,
        params: config.params,
        data: config.data
    });

    return config;
});

// ==================== 响应拦截器 ====================
Api.interceptors.response((response: AxiosResponse<ResponseData>) => {
    const requestConfig = response.config as InternalRequestConfig;
    const { data, headers } = response;
    const statusCode = data?.code;

    // 隐藏加载提示
    if (requestConfig.loading) {
        toast.close();
    }

    // 调试日志
    console.log(`[响应] ${requestConfig.apiName || requestConfig.url}`, {
        code: statusCode,
        data: data?.data,
        message: data?.msg || data?.message
    });

    // 刷新 token（如果响应头中包含新 token）
    const authHeader = headers?.["authorization"] || headers?.["Authorization"];
    if (authHeader) {
        localStorage.setItem("token", authHeader);
    }

    // 根据状态码处理响应
    switch (statusCode) {
        case 200:
        case 0: {
            // 请求成功
            return data;
        }

        case 400: {
            // 请求参数错误
            toast.fail(getErrorMessage(data, "请求参数错误"));
            return Promise.reject(data);
        }

        case 401:
        case 403: {
            // 未授权或无权限
            toast.fail(getErrorMessage(data, "未授权或无权限"));
            // 清除 token 并跳转到登录页
            localStorage.removeItem("token");
            setTimeout(() => {
                window.location.href = "/login";
            }, 1500);
            return Promise.reject(data);
        }

        case 500: {
            // 服务器错误
            toast.fail(getErrorMessage(data, "服务器错误，请稍后重试"));
            console.error(`[服务器错误] ${requestConfig.apiName || requestConfig.url}`, data);
            return Promise.reject(data);
        }

        default: {
            // 其他错误
            const errorMsg = getErrorMessage(data, `请求失败 (${statusCode})`);
            toast.fail(errorMsg);
            console.error(`[请求失败] ${requestConfig.apiName || requestConfig.url}`, {
                code: statusCode,
                data
            });
            return Promise.reject(data);
        }
    }
});

export default Api;
